<?php

namespace Kinch\LaravelScoutElasticsearch\Services;

use Elastic\Elasticsearch\Client;
use Elastic\Elasticsearch\ClientBuilder;
use Elastic\Elasticsearch\Exception\AuthenticationException;

class ElasticsearchService
{
    private $elasticsearch;
    private $indexName;
    private $typeName;
    private $bodyArray = [];
    private $id;

    /**
     * @throws AuthenticationException
     */
    public function __construct()
    {
        $config = config('elasticsearch');

        $clientBuilder = ClientBuilder::create()->setHosts(explode(',', $config['host']));

        if ($config['user'] && $config['password']) {
            $clientBuilder->setBasicAuthentication($config['user'], $config['password']);
        }

        if ($config['cert']) {
            $clientBuilder->setCABundle($config['cert']);
        }

        if ($config['cloud_id']) {
            $clientBuilder->setElasticCloudId($config['cloud_id']);
        }

        if ($config['api_key']) {
            $clientBuilder->setApiKey($config['api_key'], $config['api_id']);
        }

        $this->elasticsearch = $clientBuilder->build();
    }

    public function client(): Client
    {
        return $this->elasticsearch;
    }

    public function onIndex(string $indexName)
    {
        $this->indexName = $indexName;
        return $this;
    }

    public function onId($id)
    {
        $this->id = $id;
        return $this;
    }

    public function onType(string $typeName)
    {
        $this->typeName = $typeName;
        return $this;
    }

    public function onBody(array $body = [])
    {
        $this->bodyArray = $body;
        return $this;
    }

    /**
     * 判断索引是否存在
     * @return bool
     */
    public function existsIndex()
    {
        $params = [
            'index' => $this->indexName
        ];

        try {
            return $this->elasticsearch->indices()->exists($params)->asBool();
        }catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 创建索引 (只能创建一次)
     * @return array
     */
    public function createIndex()
    {
        $params = [
            'index' => $this->indexName,
            'body' => [
                'settings' => [
                    'number_of_shards' => 5,
                    'number_of_replicas' => 1
                ]
            ]
        ];

        try {
            return $this->elasticsearch->indices()->create($params)->asArray();
        }catch (\Exception $e) {
            return [];
        }
    }

    /**
     * 删除索引
     * @return array
     */
    public function deleteIndex()
    {
        $params = [
            'index' => $this->indexName
        ];

        try {
            return $this->elasticsearch->indices()->delete($params)->asArray();
        }catch (\Exception $e) {
            return [];
        }
    }

    /**
     * 添加文档
     * @return array
     */
    public function addDoc()
    {
        $params = [
            'index' => $this->indexName,
            'id' => $this->id,
            'type' => $this->typeName,
            'body' => $this->bodyArray
        ];

        try {
            return $this->elasticsearch->index($params)->asArray();
        }catch (\Exception $e) {
            return [];
        }
    }

    /**
     * 判断文档存在
     * @return bool
     */
    public function existsDoc()
    {
        $params = [
            'index' => $this->indexName,
            'id' => $this->id,
            'type' => $this->typeName,
        ];

        try {
            return $this->elasticsearch->exists($params)->asBool();
        }catch (\Exception $e) {
            return false;
        }
    }

    /**
     * * 获取文档
     * @return array
     */
    public function getDoc()
    {
        $params = [
            'index' => $this->indexName,
            'id' => $this->id,
            'type' => $this->typeName,
        ];

        try {
            return $this->elasticsearch->get($params)->asArray();
        }catch (\Exception $e) {
            return [];
        }
    }

    /**
     * 更新文档
     * @return array
     */
    public function updateDoc()
    {
        // 可以灵活添加新字段,最好不要乱添加
        $params = [
            'index' => $this->indexName,
            'id' => $this->id,
            'type' => $this->typeName,
            'body' => $this->bodyArray
        ];

        try {
            return $this->elasticsearch->update($params)->asArray();
        }catch (\Exception $e) {
            return [];
        }
    }

    /**
     * 删除文档
     * @return array
     */
    public function deleteDoc()
    {
        $params = [
            'index' => $this->indexName,
            'id' => $this->id,
            'type' => $this->typeName,
        ];

        try {
            return $this->elasticsearch->delete($params)->asArray();
        }catch (\Exception $e) {
            return [];
        }
    }

    /**
     * 搜索文档 (分页，排序，权重，过滤)
     * @return array
     */
    public function searchDoc()
    {
        $params = [
            'index' => $this->indexName,
            'type' => $this->typeName,
            'body' => $this->bodyArray
        ];

        try {
            return $this->elasticsearch->search($params)->asArray();
        }catch (\Exception $e) {
            return [];
        }
    }

    public function __call($method, $parameters)
    {
        return $this->elasticsearch->$method(...$parameters);
    }
}
